home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / xfd / fontgrid.c next >
Text File  |  1994-08-12  |  17KB  |  547 lines

  1. /*
  2.  * $XConsortium: fontgrid.c,v 1.25 91/07/18 14:59:57 rws Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Jim Fulton, MIT X Consortium
  24.  */
  25.  
  26.  
  27. #ifdef MSDOS
  28. #include "X11/IntrinsP.h"      /* QDK 05/12/1994  2:28pm. */
  29. #else
  30. #include "X11/IntrinsicP.h"
  31. #endif
  32. #include <X11/StringDefs.h>
  33. #include <X11/Xaw/SimpleP.h>
  34. #include <X11/Xmu/Converters.h>
  35. #ifdef MSDOS
  36. #include "fontgrip.h"
  37. #else
  38. #include "fontgridP.h"
  39. #endif
  40.  
  41.  
  42. #define Bell(w) XBell(XtDisplay(w), 50)
  43.  
  44.  
  45. static void ClassInitialize(), Initialize(), Realize(), Redisplay(), Notify();
  46. static void Destroy(), Resize(), paint_grid();
  47. static Boolean SetValues();
  48.  
  49. #define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)
  50.  
  51. static XtResource resources[] = {
  52.     { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  53.     Offset(text_font), XtRString, (XtPointer) NULL },
  54.     { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int),
  55.     Offset(cell_cols), XtRImmediate, (XtPointer) 0 },
  56.     { XtNcellRows, XtCCellRows, XtRInt, sizeof(int),
  57.     Offset(cell_rows), XtRImmediate, (XtPointer) 0 },
  58.     { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int),
  59.     Offset(cell_width), XtRImmediate, (XtPointer) 0 },
  60.     { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int),
  61.     Offset(cell_height), XtRImmediate, (XtPointer) 0 },
  62.     { XtNstartChar, XtCStartChar, XtRDimension, sizeof(Dimension),
  63.     Offset(start_char), XtRImmediate, (XtPointer) 0xffff },
  64.     { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  65.     Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground },
  66.     { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean),
  67.     Offset(center_chars), XtRImmediate, (XtPointer) FALSE },
  68.     { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean),
  69.     Offset(box_chars), XtRImmediate, (XtPointer) FALSE },
  70.     { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel),
  71.     Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground },
  72.     { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  73.     Offset(callbacks), XtRCallback, (XtPointer) NULL },
  74.     { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int),
  75.     Offset(internal_pad), XtRImmediate, (XtPointer) 4 },
  76.     { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int),
  77.     Offset(grid_width), XtRImmediate, (XtPointer) 1 },
  78. };
  79.  
  80. #undef Offset
  81.  
  82. static char defaultTranslations[] = 
  83.   "<ButtonPress>:  notify()";
  84.  
  85. static XtActionsRec actions_list[] = {
  86.     { "notify",        Notify },
  87. };
  88.  
  89. FontGridClassRec fontgridClassRec = {
  90.   { /* core fields */
  91.     /* superclass               */      (WidgetClass) &simpleClassRec,
  92.     /* class_name               */      "FontGrid",
  93.     /* widget_size              */      sizeof(FontGridRec),
  94.     /* class_initialize         */      ClassInitialize,
  95.     /* class_part_initialize    */      NULL,
  96.     /* class_inited             */      FALSE,
  97.     /* initialize               */      Initialize,
  98.     /* initialize_hook          */      NULL,
  99.     /* realize                  */      Realize,
  100.     /* actions                  */      actions_list,
  101.     /* num_actions              */      XtNumber(actions_list),
  102.     /* resources                */      resources,
  103.     /* num_resources            */      XtNumber(resources),
  104.     /* xrm_class                */      NULLQUARK,
  105.     /* compress_motion          */      TRUE,
  106.     /* compress_exposure        */      TRUE,
  107.     /* compress_enterleave      */      TRUE,
  108.     /* visible_interest         */      FALSE,
  109.     /* destroy                  */      Destroy,
  110.     /* resize                   */      Resize,
  111.     /* expose                   */      Redisplay,
  112.     /* set_values               */      SetValues,
  113.     /* set_values_hook          */      NULL,
  114.     /* set_values_almost        */      XtInheritSetValuesAlmost,
  115.     /* get_values_hook          */      NULL,
  116.     /* accept_focus             */      NULL,
  117.     /* version                  */      XtVersion,
  118.     /* callback_private         */      NULL,
  119.     /* tm_table                 */      defaultTranslations,
  120.     /* query_geometry           */      XtInheritQueryGeometry,
  121.     /* display_accelerator      */      XtInheritDisplayAccelerator,
  122.     /* extension                */      NULL
  123.   },
  124.   { /* simple fields */
  125.     /* change_sensitive        */    XtInheritChangeSensitive
  126.   }
  127. };
  128.  
  129. WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec;
  130.  
  131.  
  132. /*
  133.  * public routines
  134.  */
  135.  
  136. void GetFontGridCellDimensions (w, startp, ncolsp, nrowsp)
  137.     Widget w;
  138.     Dimension *startp;
  139.     int *ncolsp, *nrowsp;
  140. {
  141.     FontGridWidget fgw = (FontGridWidget) w;
  142.     *startp = (long)fgw->fontgrid.start_char;
  143.     *ncolsp = fgw->fontgrid.cell_cols;
  144.     *nrowsp = fgw->fontgrid.cell_rows;
  145. }
  146.  
  147.  
  148. void GetPrevNextStates (w, prevvalidp, nextvalidp)
  149.     Widget w;
  150.     Bool *prevvalidp, *nextvalidp;
  151. {
  152.     FontGridWidget fgw = (FontGridWidget) w;
  153.  
  154.     XFontStruct *fs = fgw->fontgrid.text_font;
  155.     long minn = (long) ((fs->min_byte1 << 0) | fs->min_char_or_byte2);
  156.     long maxn = (long) ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  157.  
  158.     *prevvalidp = ((long)fgw->fontgrid.start_char > minn);
  159.     *nextvalidp = (((long)fgw->fontgrid.start_char +
  160.             (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows))
  161.            < maxn);
  162. }
  163.  
  164.  
  165.  
  166. /*
  167.  * private routines and methods
  168.  */
  169.  
  170.  
  171. static GC get_gc (fgw, fore)
  172.     FontGridWidget fgw;
  173.     Pixel fore;
  174. {
  175.     XtGCMask mask;
  176.     XGCValues gcv;
  177.  
  178.     mask = (GCForeground | GCBackground | GCFunction | GCFont);
  179.     gcv.foreground = fore;
  180.     gcv.background = fgw->core.background_pixel;
  181.     gcv.function = GXcopy;
  182.     gcv.font = fgw->fontgrid.text_font->fid;
  183.     gcv.cap_style = CapProjecting;
  184.     mask |= GCCapStyle;
  185.     if (fgw->fontgrid.grid_width > 0) {
  186.     mask |= GCLineWidth;
  187.     gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : 
  188.               fgw->fontgrid.grid_width);
  189.     }
  190.     return (XtGetGC ((Widget) fgw, mask, &gcv));
  191. }
  192.  
  193.  
  194. static void ClassInitialize ()
  195. {
  196.     XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0);
  197. }
  198.  
  199.  
  200. static void Initialize (request, new)
  201.     Widget request, new;
  202. {
  203.     FontGridWidget reqfg = (FontGridWidget) request;
  204.     FontGridWidget newfg = (FontGridWidget) new;
  205.     XFontStruct *fs = newfg->fontgrid.text_font;
  206.     unsigned maxn;
  207.  
  208.     if (reqfg->fontgrid.cell_cols <= 0)
  209.       newfg->fontgrid.cell_cols = 16;
  210.  
  211.     if (reqfg->fontgrid.cell_rows <= 0) {
  212.     if (fs && fs->max_byte1 == 0) {
  213.         newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / 
  214.                      newfg->fontgrid.cell_cols) + 1;
  215.         if (newfg->fontgrid.cell_rows > 16)
  216.           newfg->fontgrid.cell_rows = 16;
  217.     } else
  218.       newfg->fontgrid.cell_rows = 16;
  219.     }
  220.  
  221.     if (reqfg->fontgrid.cell_width <= 0)
  222.       newfg->fontgrid.cell_width = (fs ? DefaultCellWidth (newfg) : 1);
  223.     if (reqfg->fontgrid.cell_height <= 0)
  224.       newfg->fontgrid.cell_height = (fs ? DefaultCellHeight (newfg) : 1);
  225.  
  226.     /* give a nice size that fits one screen full */
  227.     if (newfg->core.width == 0)
  228.       newfg->core.width = (newfg->fontgrid.cell_width *
  229.                newfg->fontgrid.cell_cols +
  230.                newfg->fontgrid.grid_width *
  231.                (newfg->fontgrid.cell_cols + 1));
  232.  
  233.     if (newfg->core.height == 0) 
  234.       newfg->core.height = (newfg->fontgrid.cell_height * 
  235.                 newfg->fontgrid.cell_rows +
  236.                 newfg->fontgrid.grid_width *
  237.                 (newfg->fontgrid.cell_rows + 1));
  238.  
  239.     /*
  240.      * select the first character
  241.      */
  242.  
  243.     if (newfg->fontgrid.start_char == 0xffff) {
  244.     newfg->fontgrid.start_char = (fs ? (unsigned)(fs->min_byte1 << 8) : 0);
  245.     }
  246.     if (fs) {
  247.     maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  248.     if (newfg->fontgrid.start_char > maxn) 
  249.       newfg->fontgrid.start_char = (maxn + 1 - 
  250.                     (newfg->fontgrid.cell_cols * 
  251.                      newfg->fontgrid.cell_rows));
  252.     }
  253. }
  254.  
  255. static void Realize (gw, valueMask, attributes)
  256.     Widget gw;
  257.     Mask *valueMask;
  258.     XSetWindowAttributes *attributes;
  259. {
  260.     FontGridWidget fgw = (FontGridWidget) gw;
  261.     FontGridPart *p = &fgw->fontgrid;
  262.  
  263.     p->text_gc = get_gc (fgw, p->foreground_pixel);
  264.     p->box_gc = get_gc (fgw, p->box_pixel);
  265.     Resize (gw);
  266.  
  267.     (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes);
  268.     return;
  269. }
  270.  
  271.  
  272.  
  273. static void Destroy (gw)
  274.     Widget gw;
  275. {
  276.     FontGridWidget fgw = (FontGridWidget) gw;
  277.  
  278.     XtReleaseGC (gw, fgw->fontgrid.text_gc);
  279.     XtReleaseGC (gw, fgw->fontgrid.box_gc);
  280. }
  281.  
  282.  
  283. static void Resize (gw)
  284.     Widget gw;
  285. {
  286.     FontGridWidget fgw = (FontGridWidget) gw;
  287.  
  288.     /* recompute in case we've changed size */
  289.     fgw->fontgrid.cell_width = CellWidth (fgw);
  290.     if (fgw->fontgrid.cell_width <= 0)
  291.     fgw->fontgrid.cell_width = 1;
  292.     fgw->fontgrid.cell_height = CellHeight (fgw);
  293.     if (fgw->fontgrid.cell_height <= 0)
  294.     fgw->fontgrid.cell_height = 1;
  295.     fgw->fontgrid.xoff = (fgw->fontgrid.cell_width -
  296.                 DefaultCellWidth (fgw)) / 2;
  297.     fgw->fontgrid.yoff = (fgw->fontgrid.cell_height -
  298.                 DefaultCellHeight (fgw)) / 2;
  299.  
  300. }
  301.  
  302.  
  303. /* ARGSUSED */
  304. static void Redisplay (gw, event, region)
  305.     Widget gw;
  306.     XEvent *event;
  307.     Region region;
  308. {
  309.     FontGridWidget fgw = (FontGridWidget) gw;
  310.     XRectangle rect;            /* bounding rect for region */
  311.     int left, right, top, bottom;    /* which cells were damaged */
  312.     int cw, ch;                /* cell size */
  313.  
  314.     if (!fgw->fontgrid.text_font) {
  315.     Bell (gw);
  316.     return;
  317.     }
  318.  
  319.     /*
  320.      * compute the left, right, top, and bottom cells that were damaged
  321.      */
  322.     XClipBox (region, &rect);
  323.     cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
  324.     ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
  325.     if ((left = (((int) rect.x) / cw)) < 0) left = 0;
  326.     right = (((int) (rect.x + rect.width - 1)) / cw);
  327.     if ((top = (((int) rect.y) / ch)) < 0) top = 0;
  328.     bottom = (((int) (rect.y + rect.height - 1)) / ch);
  329.  
  330.     paint_grid (fgw, left, top, right - left + 1, bottom - top + 1);
  331. }
  332.  
  333.  
  334. static void paint_grid (fgw, col, row, ncols, nrows)
  335.     FontGridWidget fgw;            /* widget in which to draw */
  336.     int col, row;            /* where to start */
  337.     int ncols, nrows;            /* number of cells */
  338. {
  339.     FontGridPart *p = &fgw->fontgrid;
  340.     int i, j;
  341.     Display *dpy = XtDisplay(fgw);
  342.     Window wind = XtWindow(fgw);
  343.     int cw = p->cell_width + p->grid_width;
  344.     int ch = p->cell_height + p->grid_width;
  345.     int tcols = p->cell_cols;
  346.     int trows = p->cell_rows;
  347.     int x1, y1, x2, y2, x, y;
  348.     unsigned maxn = ((p->text_font->max_byte1 << 8) |
  349.              p->text_font->max_char_or_byte2);
  350.     unsigned n, prevn;
  351.     int startx;
  352.  
  353.     if (col + ncols >= tcols) {
  354.     ncols = tcols - col;
  355.     if (ncols < 1) return;
  356.     }
  357.  
  358.     if (row + nrows >= trows) {
  359.     nrows = trows - row;
  360.     if (nrows < 1) return;
  361.     }
  362.  
  363.     /*
  364.      * paint the grid lines for the indicated rows 
  365.      */
  366.     if (p->grid_width > 0) {
  367.     int half_grid_width = p->grid_width >> 1;
  368.     x1 = col * cw + half_grid_width;
  369.     y1 = row * ch + half_grid_width;
  370.     x2 = x1 + ncols * cw;
  371.     y2 = y1 + nrows * ch;
  372.     for (i = 0, x = x1; i <= ncols; i++, x += cw) {
  373.         XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
  374.     }
  375.     for (i = 0, y = y1; i <= nrows; i++, y += ch) {
  376.         XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
  377.     }
  378.     }
  379.  
  380.     
  381.     /*
  382.      * Draw a character in every box; treat all fonts as if they were 16bit
  383.      * fonts.  Store the high eight bits in byte1 and the low eight bits in 
  384.      * byte2.
  385.      */
  386.     prevn = p->start_char + col + row * tcols;
  387.     startx = col * cw + p->internal_pad + p->grid_width;
  388.     for (j = 0,
  389.      y = row * ch + p->internal_pad + p->grid_width + p->text_font->ascent;
  390.      j < nrows; j++, y += ch) {
  391.     n = prevn;
  392.     for (i = 0, x = startx; i < ncols; i++, x += cw) {
  393.         XChar2b thechar;
  394.         int xoff = p->xoff, yoff = p->yoff;
  395.  
  396.         if (n > maxn) goto done;    /* no break out of nested */
  397.  
  398.         thechar.byte1 = (n >> 8);    /* high eight bits */
  399.         thechar.byte2 = (n & 255);    /* low eight bits */
  400.         if (p->box_chars || p->center_chars) {
  401.         XCharStruct metrics;
  402.         int direction, fontascent, fontdescent;
  403.  
  404.         XTextExtents16 (p->text_font, &thechar, 1, &direction,
  405.                 &fontascent, &fontdescent, &metrics);
  406.  
  407.         if (p->center_chars) {
  408.             /*
  409.              * We want to move the origin by enough to center the ink
  410.              * within the cell.  The left edge will then be at 
  411.              * (cell_width - (rbearing - lbearing)) / 2; so we subtract
  412.              * the lbearing to find the origin.  Ditto for vertical.
  413.              */
  414.             xoff = (((p->cell_width -
  415.                   (metrics.rbearing - metrics.lbearing)) / 2) -
  416.                 p->internal_pad - metrics.lbearing);
  417.             yoff = (((p->cell_height - 
  418.                   (metrics.descent + metrics.ascent)) / 2) -
  419.                 p->internal_pad -
  420.                 p->text_font->ascent + metrics.ascent);
  421.         }
  422.         if (p->box_chars) {
  423.             XDrawRectangle (dpy, wind, p->box_gc,
  424.                     x + xoff, y + yoff - p->text_font->ascent, 
  425.                     metrics.width - 1,
  426.                     fontascent + fontdescent - 1);
  427.         }
  428.         }
  429.         XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff,
  430.                &thechar, 1);
  431.         n++;
  432.     }
  433.     prevn += tcols;
  434.     }
  435.  
  436.   done:
  437.     return;
  438. }
  439.  
  440. /*ARGSUSED*/
  441. static Boolean SetValues (current, request, new, args, num_args)
  442.     Widget current, request, new;
  443.     ArgList args;
  444.     Cardinal *num_args;
  445. {
  446.     FontGridWidget curfg = (FontGridWidget) current;
  447.     FontGridWidget newfg = (FontGridWidget) new;
  448.     Boolean redisplay = FALSE;
  449.  
  450.     if (curfg->fontgrid.text_font != newfg->fontgrid.text_font ||
  451.     curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) {
  452.     newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
  453.     newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
  454.     redisplay = TRUE;
  455.     }
  456.  
  457.     if (curfg->fontgrid.foreground_pixel != newfg->fontgrid.foreground_pixel) {
  458.     XtReleaseGC (new, curfg->fontgrid.text_gc);
  459.     newfg->fontgrid.text_gc = get_gc (newfg,
  460.                       newfg->fontgrid.foreground_pixel);
  461.     redisplay = TRUE;
  462.     }
  463.  
  464.     if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) {
  465.     XtReleaseGC (new, curfg->fontgrid.text_gc);
  466.     newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel);
  467.     redisplay = TRUE;
  468.     }
  469.  
  470.     if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars ||
  471.     curfg->fontgrid.box_chars != newfg->fontgrid.box_chars)
  472.       redisplay = TRUE;
  473.  
  474.     if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) {
  475.     XFontStruct *fs = newfg->fontgrid.text_font;
  476.     unsigned maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  477.  
  478.     if (newfg->fontgrid.start_char > maxn) 
  479.       newfg->fontgrid.start_char = (maxn + 1 - 
  480.                     (newfg->fontgrid.cell_cols * 
  481.                      newfg->fontgrid.cell_rows));
  482.  
  483.     redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char);
  484.     }
  485.  
  486.     return redisplay;
  487. }
  488.  
  489.  
  490. /* ARGSUSED */
  491. static void Notify (gw, event, params, nparams)
  492.     Widget gw;
  493.     XEvent *event;
  494.     String *params;
  495.     Cardinal *nparams;
  496. {
  497.     FontGridWidget fgw = (FontGridWidget) gw;
  498.     int x, y;                /* where the event happened */
  499.     FontGridCharRec rec;        /* callback data */
  500.  
  501.     /*
  502.      * only allow events with (x,y)
  503.      */
  504.     switch (event->type) {
  505.       case KeyPress:
  506.       case KeyRelease:
  507.     x = event->xkey.x;
  508.     y = event->xkey.y;
  509.     break;
  510.       case ButtonPress:
  511.       case ButtonRelease:
  512.     x = event->xbutton.x;
  513.     y = event->xbutton.y;
  514.     break;
  515.       case MotionNotify:
  516.     x = event->xmotion.x;
  517.     y = event->xmotion.y;
  518.     break;
  519.       default:
  520.     Bell (gw);
  521.     return;
  522.     }
  523.  
  524.     /*
  525.      * compute the callback data
  526.      */
  527.     {
  528.     int cw = fgw->fontgrid.cell_width, ch = fgw->fontgrid.cell_height;
  529.     unsigned n;
  530.  
  531.     if (x > (fgw->fontgrid.cell_cols * cw)) {
  532.         Bell (gw);
  533.         return;
  534.     }
  535.  
  536.     n= (fgw->fontgrid.start_char + 
  537.         ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw));
  538.  
  539.     rec.thefont = fgw->fontgrid.text_font;
  540.     rec.thechar.byte1 = (n >> 8);
  541.     rec.thechar.byte2 = (n & 255);
  542.     }
  543.  
  544.     XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec);
  545. }
  546.  
  547.